import { assetManager, JsonAsset, log, resources, TextAsset } from 'cc';
import { ResourceManager } from './ResourceManager';
import { ConfigManager } from './ConfigManager';
import { GlobalManager } from '../global/GlobalManager';

/**
 * JSON配置管理器
 * 专门处理JSON配置的加载、更新和热重载
 */
export class JsonConfigManager {
    private static _instance: JsonConfigManager;
    public static get instance(): JsonConfigManager {
        if (!this._instance) {
            this._instance = new JsonConfigManager();
        }
        return this._instance;
    }

    private configCache: Map<string, any> = new Map();
    private lastUpdateTime: Map<string, number> = new Map();
    private updateInterval: number = 5 * 60 * 1000; // 5分钟检查一次更新
    private cacheSizeLimit: number = 100; // 缓存大小限制（条目数）
    private cacheHits: number = 0; // 缓存命中次数
    private cacheMisses: number = 0; // 缓存未命中次数

    private constructor() { }

    /**
     * 初始化并预热缓存
     * @param configs 预加载的配置列表
     */
    public async initCache(configs?: { path: string, configKey: string, isRemote: boolean }[]): Promise<void> {
        console.log(`[JsonConfigManager] 初始化缓存`);
        
        if (configs && configs.length > 0) {
            console.log(`[JsonConfigManager] 预热缓存，加载 ${configs.length} 个配置`);
            const loadPromises = configs.map(config => 
                this.loadJsonConfig(config.path, config.configKey, config.isRemote)
            );
            await Promise.all(loadPromises);
            console.log(`[JsonConfigManager] 缓存预热完成，已加载 ${this.configCache.size} 个配置`);
        }
    }

    /**
     * 加载JSON配置
     * @param path JSON文件路径
     * @param configKey 配置键名
     * @param forceRemote 是否强制使用远程加载
     */
    public async loadJsonConfig(path: string, configKey: string, forceRemote: boolean = true): Promise<any> {
        try {
            // 检查缓存是否存在且未过期
            if (this.configCache.has(configKey) && !this.shouldUpdateConfig(configKey)) {
                console.log(`[JsonConfigManager] 使用缓存配置: ${configKey}`);
                return this.configCache.get(configKey);
            }

            // 优先远程加载，以便热更新
            const shouldUseRemote = forceRemote || GlobalManager.shouldUseRemote(forceRemote, false);

            if (shouldUseRemote) {
                console.log(`shouldUseRemote配置远程加载: ${shouldUseRemote}`);
                const config = await this.loadRemoteJson(path, configKey);
                if (config) return config;
            }

            const config = await this.loadLocalJson(path, configKey);
            if (config) return config;

            console.error(`[JsonConfigManager] 配置加载失败: ${configKey}`);
            return null;

        } catch (error) {
            console.error(`[JsonConfigManager] 配置加载异常: ${configKey}`, error);
            return null;
        }
    }

   

    /**
     * Promise 封装的远程 JsonAsset 加载
     */
    private loadRemoteJsonAsset(url: string): Promise<JsonAsset> {
        return new Promise((resolve, reject) => {
            assetManager.loadRemote(url, JsonAsset, (err, asset) => {
                if (err) {
                    reject(err);
                } else {
                    resolve(asset as JsonAsset);
                }
            });
        });
    }

    /**
     * 远程加载JSON
     */
    private async loadRemoteJson(path: string, configKey: string): Promise<any> {
        try {
            const url = GlobalManager.getRemoteJsonUrl(path);
            // console.log(`[JsonConfigManager] 远程加载JSON: ${url}`);
            const asset = await this.loadRemoteJsonAsset(url);
            // console.log('[JsonConfigManager] asset:', asset);
            // console.log('[JsonConfigManager] asset.constructor.name:', asset && asset.constructor && asset.constructor.name);
            // console.log('[JsonConfigManager] asset.json:', asset && asset.json);
            let jsonData = null;
            if (asset && asset.json) {
                jsonData = asset.json;
            }
            if (jsonData) {
                this.configCache.set(configKey, jsonData);
                this.lastUpdateTime.set(configKey, Date.now());
                ConfigManager.instance.setConfig(configKey, jsonData);
                console.log(`[JsonConfigManager] 远程JSON加载成功: ${configKey}`);
                return jsonData;
            }
        } catch (error) {
            console.log(`[JsonConfigManager] 远程JSON加载失败: ${path}`, error);
        }
        return null;
    }

    /**
     * 本地加载JSON
     */
    private async loadLocalJson(path: string, configKey: string): Promise<any> {
        try {
            // 移除硬编码路径，使用传入的路径
            // 如果路径包含扩展名，则移除扩展名
            const resourcePath = path.replace(/\.(json|JSON)$/, '');
            console.log(`[JsonConfigManager] 本地加载JSON: ${resourcePath}`);
            
            const asset = await new Promise<any>((resolve) => {
                ResourceManager.instance.loadJson({name: resourcePath}, (json) => {
                    resolve({ json });
                });
            });
            let jsonData = null;
            if (asset && asset.json) {
                try {
                    jsonData = asset.json;
                } catch (e) {
                    console.error(`[JsonConfigManager] 解析本地JSON失败: ${path}`, e);
                }
            }
            if (jsonData) {
                this.configCache.set(configKey, jsonData);
                this.lastUpdateTime.set(configKey, Date.now());
                ConfigManager.instance.setConfig(configKey, jsonData);
                console.log(`[JsonConfigManager] 本地JSON加载成功: ${configKey}`);
                return jsonData;
            }
        } catch (error) {
            console.log(`[JsonConfigManager] 本地JSON加载失败: ${path}`, error);
        }
        return null;
    }

    /**
     * 热更新配置
     * @param configKey 配置键名
     * @param path JSON文件路径
     */
    public async hotUpdateConfig(configKey: string, path: string): Promise<boolean> {
        console.log(`[JsonConfigManager] 热更新配置: ${configKey}`);

        try {
            const newConfig = await this.loadRemoteJson(path, configKey);
            if (newConfig) {
                console.log(`[JsonConfigManager] 配置热更新成功: ${configKey}`);
                return true;
            }
        } catch (error) {
            console.error(`[JsonConfigManager] 配置热更新失败: ${configKey}`, error);
        }
        return false;
    }

    /**
     * 批量热更新所有配置
     */
    public async hotUpdateAllConfigs(): Promise<{ success: string[], failed: string[] }> {
        console.log(`[JsonConfigManager] 开始批量热更新配置`);

        const success: string[] = [];
        const failed: string[] = [];

        for (const item of GlobalManager.preloadJsonList) {
            const result = await this.hotUpdateConfig(item.configKey, item.path);
            if (result) {
                success.push(item.configKey);
            } else {
                failed.push(item.configKey);
            }
        }

        console.log(`[JsonConfigManager] 批量热更新完成 - 成功: ${success.length}, 失败: ${failed.length}`);
        return { success, failed };
    }

    /**
     * 检查配置是否需要更新
     * @param configKey 配置键名
     */
    public shouldUpdateConfig(configKey: string): boolean {
        const lastUpdate = this.lastUpdateTime.get(configKey);
        if (!lastUpdate) {
            console.log(`[JsonConfigManager] 配置 ${configKey} 没有最后更新时间记录，需要更新`);
            return true;
        }

        const timeSinceUpdate = Date.now() - lastUpdate;
        const needsUpdate = timeSinceUpdate > this.updateInterval;
        
        if (needsUpdate) {
            console.log(`[JsonConfigManager] 配置 ${configKey} 已过期（${Math.floor(timeSinceUpdate/1000)}秒），需要更新`);
        }
        
        return needsUpdate;
    }
    
    /**
     * 管理缓存大小，如果超过限制则移除最旧的条目
     */
    private manageCacheSize(): void {
        if (this.configCache.size <= this.cacheSizeLimit) return;
        
        console.log(`[JsonConfigManager] 缓存大小 ${this.configCache.size} 超过限制 ${this.cacheSizeLimit}，清理旧条目`);
        
        // 按最后更新时间排序
        const sortedEntries = Array.from(this.lastUpdateTime.entries())
            .sort((a, b) => a[1] - b[1]);
        
        // 移除最旧的条目，直到缓存大小低于限制
        const entriesToRemove = sortedEntries.slice(0, this.configCache.size - this.cacheSizeLimit);
        for (const [key] of entriesToRemove) {
            this.configCache.delete(key);
            this.lastUpdateTime.delete(key);
            console.log(`[JsonConfigManager] 从缓存中移除旧条目: ${key}`);
        }
    }

    /**
     * 获取缓存统计信息
     */
    public getCacheStats(): { size: number, hits: number, misses: number, hitRate: string } {
        const total = this.cacheHits + this.cacheMisses;
        const hitRate = total > 0 ? (this.cacheHits / total * 100).toFixed(2) + '%' : '0%';
        
        return {
            size: this.configCache.size,
            hits: this.cacheHits,
            misses: this.cacheMisses,
            hitRate
        };
    }

    /**
     * 设置缓存参数
     * @param updateInterval 更新间隔（毫秒）
     * @param cacheSizeLimit 缓存大小限制（条目数）
     */
    public setCacheParams(updateInterval?: number, cacheSizeLimit?: number): void {
        if (updateInterval !== undefined) this.updateInterval = updateInterval;
        if (cacheSizeLimit !== undefined) {
            this.cacheSizeLimit = cacheSizeLimit;
            this.manageCacheSize(); // 立即应用新的大小限制
        }
        
        console.log(`[JsonConfigManager] 缓存参数已更新 - 更新间隔: ${this.updateInterval}ms, 大小限制: ${this.cacheSizeLimit}条目`);
    }

    /**
     * 获取配置
     * @param configKey 配置键名
     */
    public getConfig(configKey: string): any {
        return this.configCache.get(configKey) || ConfigManager.instance.getConfig(configKey);
    }

    /**
     * 设置配置
     * @param configKey 配置键名
     * @param config 配置数据
     */
    public setConfig(configKey: string, config: any): void {
        this.configCache.set(configKey, config);
        this.lastUpdateTime.set(configKey, Date.now());
        ConfigManager.instance.setConfig(configKey, config);
    }

    /**
     * 清除配置缓存
     */
    public clearCache(): void {
        this.configCache.clear();
        this.lastUpdateTime.clear();
        console.log(`[JsonConfigManager] 配置缓存已清除`);
    }

    /**
     * 获取缓存信息
     */
    public getCacheInfo(): { configCount: number; cachedConfigs: string[]; lastUpdates: Record<string, number> } {
        const lastUpdates: Record<string, number> = {};
        this.lastUpdateTime.forEach((time, key) => {
            lastUpdates[key] = time;
        });

        return {
            configCount: this.configCache.size,
            cachedConfigs: Array.from(this.configCache.keys()),
            lastUpdates
        };
    }

    /**
     * 设置更新检查间隔
     * @param interval 间隔时间（毫秒）
     */
    public setUpdateInterval(interval: number): void {
        this.updateInterval = interval;
        console.log(`[JsonConfigManager] 更新检查间隔设置为: ${interval}ms`);
    }
} 